import { logger } from '../utils/logger'

/**
 * 音频播放器配置接口
 */
export interface AudioPlayerConfig {
  idleAnimation: string
  speakingAnimation: string
  onAnimationChange: (animation: string) => void
}

/**
 * 音频播放器服务类
 * 处理音频流的播放、缓冲和管理
 */
export class AudioPlayerService {
  private audio: HTMLAudioElement
  private mediaSource: MediaSource
  private sourceBuffer: SourceBuffer | null = null
  private cacheBuffers: ArrayBuffer[] = []
  private currentAnimation: string
  private idleAnimation: string
  private speakingAnimation: string
  private animationCallback: (animation: string) => void
  
  constructor(config: AudioPlayerConfig) {
    this.idleAnimation = config.idleAnimation
    this.speakingAnimation = config.speakingAnimation
    this.currentAnimation = config.idleAnimation
    this.animationCallback = config.onAnimationChange
    
    // 初始化 MediaSource 
    const MediaSourceConstructor = window.MediaSource || (window as any).WebkitMediaSource || (window as any).ManagedMediaSource
    this.mediaSource = new MediaSourceConstructor()
    
    // 设置音频元素
    this.audio = new Audio()
    this.audio.autoplay = true
    this.audio.src = URL.createObjectURL(this.mediaSource)
    
    // 监听事件
    this.setupEvents()
  }
  
  /**
   * 设置事件监听器
   */
  private setupEvents(): void {
    this.mediaSource.addEventListener('sourceopen', () => {
      if (!this.sourceBuffer) {
        try {
          this.sourceBuffer = this.mediaSource.addSourceBuffer('audio/mpeg')
          logger.debug('AudioPlayer', '音频源缓冲区已创建')
        } catch (err) {
          logger.error('AudioPlayer', '创建音频源缓冲区失败', err)
        }
      }
    })
    
    this.audio.addEventListener('play', () => {
      this.currentAnimation = this.speakingAnimation
      this.animationCallback(this.currentAnimation)
    })
    
    this.audio.addEventListener('ended', () => {
      this.currentAnimation = this.idleAnimation
      this.animationCallback(this.currentAnimation)
    })
    
    this.audio.addEventListener('pause', () => {
      this.currentAnimation = this.idleAnimation
      this.animationCallback(this.currentAnimation)
    })
  }
  
  /**
   * 添加音频数据到缓冲区
   * @param base64Audio base64编码的音频数据
   */
  public appendAudioData(base64Audio: string): void {
    if (!base64Audio || !base64Audio.length) return
    
    try {
      // 解码 base64
      const binaryString = atob(base64Audio)
      const bytes = new Uint8Array(binaryString.length)
      for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i)
      }
      
      const audioData = bytes.buffer
      
      // 添加到缓冲区
      if (this.sourceBuffer?.updating) {
        this.cacheBuffers.push(audioData)
      } else if (this.sourceBuffer) {
        if (this.cacheBuffers.length > 0) {
          this.cacheBuffers.push(audioData)
          const firstBuffer = this.cacheBuffers.shift()!
          this.sourceBuffer.appendBuffer(firstBuffer)
        } else {
          this.sourceBuffer.appendBuffer(audioData)
        }
      }
      
      // 如果音频暂停，尝试播放
      if (this.audio.paused) {
        this.audio.play().catch(err => logger.error('AudioPlayer', '播放音频失败', err))
      }
    } catch (err) {
      logger.error('AudioPlayer', '处理音频数据失败', err)
    }
  }
  
  /**
   * 结束音频流
   */
  public endStream(): void {
    if (!this.mediaSource || this.mediaSource.readyState !== 'open') return
    
    const endTimer = setInterval(() => {
      // 处理剩余的缓冲区
      if (this.cacheBuffers.length > 0 && this.sourceBuffer && !this.sourceBuffer.updating) {
        const buffer = this.cacheBuffers.shift()!
        this.sourceBuffer.appendBuffer(buffer)
      } 
      // 如果没有更多数据且不在更新中，结束流
      else if (this.cacheBuffers.length === 0 && this.sourceBuffer && !this.sourceBuffer.updating) {
        try {
          this.mediaSource.endOfStream()
          clearInterval(endTimer)
        } catch (err) {
          logger.error('AudioPlayer', '结束媒体流失败', err)
        }
      }
    }, 100)
  }
  
  /**
   * 重置播放器状态
   */
  public reset(): void {
    this.cacheBuffers = []
    this.currentAnimation = this.idleAnimation
    this.animationCallback(this.currentAnimation)
    
    // 重新创建媒体源
    if (this.mediaSource.readyState === 'open') {
      try {
        this.mediaSource.endOfStream()
      } catch (err) {
        logger.error('AudioPlayer', '重置时结束媒体流失败', err)
      }
    }
    
    // 重新创建 MediaSource
    const MediaSourceConstructor = window.MediaSource || (window as any).WebkitMediaSource || (window as any).ManagedMediaSource
    this.mediaSource = new MediaSourceConstructor()
    this.sourceBuffer = null
    
    // 更新音频元素
    this.audio.src = URL.createObjectURL(this.mediaSource)
    this.setupEvents()
  }
} 